/**
 *******************************************************************************
 * @file comm_ttl.c
 * @author .ISS_AUTO (hudandan@issauto.com)
 * @date 2024-06-07  1. Base version.
 *       2024-09-04  1. 更新cli模块.
 *
 * @brief This file is interfaces for user communication.
 *
 * @copyright Copyright (c) 2024 ISSAUTO TECH Co., Ltd. All rights reserved.
 *
 *******************************************************************************
 */
/* Private Includes ----------------------------------------------------------*/
#include "comm_ttl.h"
#include "commun_uart.h"

/* Private define ------------------------------------------------------------*/
#define Com_log(M, ...)          USER_PRINTF(M, ##__VA_ARGS__)

#define	COMMUN_STATIC  static

/* Private variables ---------------------------------------------------------*/
COMMUN_STATIC unsigned char RING_RX_BUF[COMM_485_RX_BUF_SIZE * 2] = {0};

/* Exported function prototypes ----------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/*******************************************************************************
 *                            cli add & delete
********************************************************************************/
#if (RS485_CLI_ENABLE)

/* Private variables ---------------------------------------------------------*/
COMMUN_STATIC hcli_obj_t rs485_cli_adapt; /*!< 定义hcli控制器 */
COMMUN_STATIC hcli_adapter_t rs485_cli_controller; /*!< HCLI适配器 */
COMMUN_STATIC unsigned char rs485_cli_rx_buffer[COMM_485_RX_BUF_SIZE + 16U] = {0};

/* Private functions ---------------------------------------------------------*/

hcli_obj_t *rs485cli_obj_get(void)
{
    return &rs485_cli_adapt;
}

int rs485cli_cmds_add(hcli_cmd_t *cmd, unsigned int n)
{
    return hcli_cmds_add(&rs485_cli_adapt, cmd, n);
}

int rs485cli_cmds_del(hcli_cmd_t *cmd, unsigned int n)
{
    return hcli_cmds_del(&rs485_cli_adapt, cmd, n);
}

static void cli_protocol_process(void *obj, void *buf, unsigned int len)
{
    hcli_recv_process((hcli_obj_t *)obj, (char *)buf, len);
}

#if (0)
/* CLI USER CODE BEGIN -------------------------------------------------------*/
static void cli_485_handler(unsigned int argc, char *argv[], void *userdata);

/**
 * @brief   CLI表
 */
static const hcli_cmd_t dm_cli_cmds[] = {
    {"@485", "@485 help", 0, 2, cli_485_handler},
};

static void cli_485_handler(unsigned int argc, char *argv[], void *userdata)
{
    hcli_obj_t *hcli = (hcli_obj_t *)userdata;

    if (argc < 2) {
        return;
    }

    if (strcmp(argv[ARGC_N_IDX_CMD], "help") == 0) {
        hcli->printf(hcli, "\"%s did <num>\\r\\n\"\r\n", hcli->adapt.cli_cmds_list[hcli->cli_index]->name);
    }
}

/* CLI USER CODE END   -------------------------------------------------------*/
#endif


#endif

/*******************************************************************************
 *                              Communication
********************************************************************************/

#if (0)
#define PRINTF_STRING_SIZE                    (256U)

/**
 * @brief uart printf function
 *
 * @param format
 * @param ...
 */
extern void uart_printf(uint8_t chan, const char *format, ...)
{
    char uart_printfStr[PRINTF_STRING_SIZE];
    int length;
    va_list args;

    va_start(args, format);
    length = (int)vsnprintf((char *)uart_printfStr, PRINTF_STRING_SIZE, (char *)format, args);
    va_end(args);

    (void)USARTx_SendData_Blocking(chan, (const uint8_t *)uart_printfStr, length);
}
#endif

/**
 * @brief Transmits data
 *
 * @param pBuf
 * @param pBufLen
 */
extern unsigned int RS485_Transmit_Data(const void *pBuf, uint32_t pBufLen)
{
    // USER_PRINTF("[RS485] > ");
    // USER_PRINTF("%c\r\n", (i_showUtf8Hex((uint8_t *)pBuf, pBufLen), ','));

    return USARTx_SendData_Blocking(UART_CHANNEL_TTL, (const uint8_t *)pBuf, pBufLen);
}

/**
 * @brief Read data
 *
 * @param pBuf
 * @param pBufLen
 */
extern unsigned int RS485_Read_Data(void *buf, unsigned int len)
{
    return comm_receive_bytes_pop(COMM_CHANNEL_TTL, (uint8_t *)buf, len);
}

/*******************************************************************************
 *                                Comm Task
********************************************************************************/

/**
 * @brief valve deinitialization.
 *
 * @param[in] void
 * @return void
 */
void Comm_DeInit(void)
{
    #if (RS485_CLI_ENABLE)
    rs485_cli_adapt.printf(&rs485_cli_adapt, "@s@\r\n");
    #endif

    /*!< Hardware deinitialization -------------------------------------*/
    /** USART2 GPIO Configures
    PA2 ------> USART2_TX
    PA3 ------> USART2_RX
    */
    GPIO_InitType GPIO_InitStructure;

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);

    /* Configure USART2 Tx as input floating */
    GPIO_InitStructure.Pin = GPIO_PIN_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    /* Configure USART2 Rx as input floating */
    GPIO_InitStructure.Pin       = GPIO_PIN_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    NVIC_DisableIRQ(UART_IRQn_485); //!< Uartx interrupt disabled

    /*!< Software deinitialization -------------------------------------*/
    Comm_RingQueue_Clear(COMM_CHANNEL_TTL);

}

/**
 * @brief Software/Hardware Initialization.
 *
 * @param[in] void
 * @return void
 */
void Comm_Init(void)
{
    /* Initialization Communication parameters -------------------------------*/

    UartX_Configuration(UART_CHANNEL_TTL, UART_BAUDRATE_485);
    UartX_ConfigurationInt(UART_CHANNEL_TTL, ENABLE, 2);
    Comm_RingQueue_Buff_Init(COMM_CHANNEL_TTL,
                             RING_RX_BUF, sizeof(RING_RX_BUF),
                             NULL, 0U);


    /* Initialization uart protocol information -------------------------------*/
    #if (RS485_CLI_ENABLE)
    memset((void *)&rs485_cli_controller, 0, sizeof(rs485_cli_controller));

    rs485_cli_controller.read_passthrough = NULL; //!< 发送透传接口
    rs485_cli_controller.write         = RS485_Transmit_Data;
    rs485_cli_controller.read          = RS485_Read_Data;
    rs485_cli_controller.user_process  = cli_protocol_process;
    rs485_cli_controller.echo          = 0; //!< 关闭回显
    rs485_cli_controller.cli_cmds_num  = 0;
    rs485_cli_controller.cli_buf       = rs485_cli_rx_buffer;
    rs485_cli_controller.cli_bufsize   = sizeof(rs485_cli_rx_buffer);
    rs485_cli_controller.cli_cnt       = 0;
    rs485_cli_controller.cli_timer     = 0;

    /*!< 初始化hcli控制器 */
    hcli_init(&rs485_cli_adapt, &rs485_cli_controller);

    #if (0)
    /*!< 添加待处理命令行 */
    (void)rs485cli_cmds_add((hcli_cmd_t *)dm_cli_cmds, sizeof(dm_cli_cmds) / sizeof(hcli_cmd_t));
    #endif

    rs485_cli_adapt.printf(&rs485_cli_adapt, "\r\n\r\n@w@\r\n");

    #endif

}

/**
 * @brief Handle function for User Application Driver layer
 *
 * @param[in] void
 * @return[out] void
 */
void Comm_Handle(void)
{
    #if (RS485_CLI_ENABLE)
    /*!< 命令行任务轮询*/
    hcli_process(&rs485_cli_adapt, 2);
    #endif
}

/* END OF FILE ---------------------------------------------------------------*/
